/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package quizzempire.model;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.logging.Level;
import java.util.logging.Logger;
import quizzempire.model.statemachine.AwaitsInstruction;
import quizzempire.model.statemachine.PrepareGame;
import quizzempire.model.statemachine.State;

/**
 *
 * @author Paulo
 */
public class Model extends IModel {
    //---------- ATTRIBUTES ---------

    final String about = "<html><div style=\"text-align: center;\">Jorge Correia (a21220313@alunos.isec.pt)<br>"
            + "Luís Vieira(a21200476@alunos.isec.pt)<br>"
            + "Paulo Duarte(a21220336@alunos.isec.pt)<br>"
            + "Tony Mendes(a21190876@alunos.isec.pt)<br>"
            + "Victor Soares(a21220721@alunos.isec.pt)</div></html>";
    State state;
    Quizz activeQuizz;
    String quizzesFolders;
    boolean hasChanged = false;
    ArrayList<String> quizzList = new ArrayList<String>();

    public Model(String quizzesFolders) {
        this.quizzesFolders = quizzesFolders;
        state = new AwaitsInstruction(this);
    }

    //---------- METHODS ---------
    @Override
    public String getAbout() {
        return about;
    }

    public String getQuizzesFolder() {
        return quizzesFolders;
    }

    public void setQuizzesFolders(String quizzesFolders) {
        this.quizzesFolders = quizzesFolders;
    }

    public void setActiveQuizz(Quizz quizz) {
        activeQuizz = quizz;
    }

    public Quizz getActiveQuizz() {
        return activeQuizz;
    }

    public void setChanges() {
        hasChanged = true;
    }

    private boolean changed() {
        boolean aux = hasChanged;
        hasChanged = false;
        return aux;
    }
    
    //so para teste
    public void setQuizzList(String nome) {
       quizzList.add(nome);
    }
    
    public void updateQuizzList() {
        File folder = new File(quizzesFolders);
        quizzList.clear();

        File[] files = folder.listFiles();

        for (int i = 0; i < files.length; i++) {
            quizzList.add(files[i].getName());
        }
    }

    public String[] getQuizzList() {
        String[] aux = new String[quizzList.size()];
        aux =  quizzList.toArray(aux);
        return aux;
    }

    public String getQuizzFileName(int quizzId) throws Exception {
        if (quizzId >= 0 && quizzId < quizzList.size()) {
            return quizzList.get(quizzId);
        }

        throw new Exception("QuizzID invalid");
    }

    public int loadQuizz(String filePath) {
        File file = new File(filePath);

        if (!file.isFile()) {
            return -1;
        }
        
        ObjectInputStream ois;
        
        try {
            ois = new ObjectInputStream(new FileInputStream(file));
            
            Quizz load = (Quizz) ois.readObject();
            ois.close();

        } catch (IOException ex) {
            Logger.getLogger(PrepareGame.class.getName()).log(Level.SEVERE, null, ex);
            return -1;
        } catch (ClassNotFoundException ex) {
            Logger.getLogger(PrepareGame.class.getName()).log(Level.SEVERE, null, ex);
            return -1;
        }

        if (file.getAbsolutePath().startsWith(this.getQuizzesFolder()))
            return -2;

        File newFile = new File(this.getQuizzesFolder() + File.separator + file.getName());
        int i = 1;

        while (true) {
            if (!newFile.exists()) {
                try {
                    System.out.println(newFile.createNewFile());
                } catch (IOException ex) {
                    Logger.getLogger(PrepareGame.class.getName()).log(Level.SEVERE, null, ex);
                }
                break;
            }
            newFile = new File(this.getQuizzesFolder() + File.separator + file.getName().substring(0, file.getName().length() - 4) + " (" + i + ")" + file.getName().substring(file.getName().length() - 4, file.getName().length()));
            i++;
        }

        try {
            InputStream in = new FileInputStream(file);
            OutputStream out = new FileOutputStream(newFile);

            byte[] buf = new byte[1024];
            int len;
            while ((len = in.read(buf)) > 0) {
                out.write(buf, 0, len);
            }

            in.close();
            out.close();

        } catch (FileNotFoundException ex) {
            Logger.getLogger(PrepareGame.class.getName()).log(Level.SEVERE, null, ex);
            return -1;
        } catch (IOException ex) {
            Logger.getLogger(PrepareGame.class.getName()).log(Level.SEVERE, null, ex);
            newFile.delete();
            return -1;
        }
        
        updateQuizzList();
        setChanges();
        state = state.loadQuizz(filePath);
        if (changed())
        {
            setChanged();
            notifyObservers();
        }
        return 1;
    }

    @Override
    public void startGame() {
        state = state.startGame();
        if (changed())
        {
            setChanged();
            notifyObservers();
        }
    }

    @Override
    public State getState() {
        return state;
    }

    @Override
    public void restart() {
        state = state.restart();
        if (changed())
        {
            setChanged();
            notifyObservers();
        }
    }

    @Override
    public void setName(String text) {
        state = state.setName(text);
        if (changed())
        {
            setChanged();
            notifyObservers();
        }
    }

    @Override
    public void setAutor(String text) {
        state = state.setCreator(text);
        if (changed())
        {
            setChanged();
            notifyObservers();
        }
    }

    @Override
    public void setDescription(String text) {
        state = state.setDescription(text);
        if (changed())
        {
            setChanged();
            notifyObservers();
        }
    }

    @Override
    public void setGenre(String text) {
        state = state.setGenre(text);
        if (changed())
        {
            setChanged();
            notifyObservers();
        }
    }

    @Override
    public void setPassword(String pass) {
        state = state.setPassword(pass);
        if (changed())
        {
            setChanged();
            notifyObservers();
        }
    }

    @Override
    public void setNQuestions(int[] nQuestions) {
        state = state.setNQuestions(nQuestions);
        if (changed())
        {
            setChanged();
            notifyObservers();
        }
    }

    @Override
    public void setDifficulties(boolean[] difficulties) {
        state = state.setDifficulties(difficulties);
        if (changed())
        {
            setChanged();
            notifyObservers();
        }
    }

    @Override
    public void editQuestons() {
        state = state.editQuestions();
        if (changed())
        {
            setChanged();
            notifyObservers();
        }
    }

    @Override
    public IQuizz getQuizzViewer() {
        return activeQuizz;
    }

    public boolean isHasChanged() {
        return hasChanged;
    }

    @Override
    public void addQuestion(String text) {
        state = state.addQuestion(text);
        if (changed())
        {
            setChanged();
            notifyObservers();
        }
    }

    @Override
    public void back() {
        state = state.back();
        if (changed())
        {
            setChanged();
            notifyObservers();
        }
    }

    @Override
    public void removeQuestion(int selectedid) { 
        state = state.removeQuestion(selectedid);
        if (changed())
        {
            setChanged();
            notifyObservers();
        }
    }

    @Override
    public void setQuestionDifficulty(int selectedid, int dif) {
        state = state.setQuestionDifficulty(selectedid, dif);
        if (changed())
        {
            setChanged();
            notifyObservers();
        }
    }

    @Override
    public void setQuestionText(int selectedid, String text) {
        state = state.setQuestionText(selectedid, text);
        if (changed())
        {
            setChanged();
            notifyObservers();
        }
    }

    @Override
    public void setQuestionAnswers(int selectedid, String[] a) {
        state = state.setQuestionAnswers(selectedid, a);
        if (changed())
        {
            setChanged();
            notifyObservers();
        }
    }

    @Override
    public void setIndexCorrect(int selectedid, int correct) {
        state = state.setIndexCorrect(selectedid, correct);
        if (changed())
        {
            setChanged();
            notifyObservers();
        }
    }

    @Override
    public void setQuestionName(int selectedid, String text) {
        state = state.setQuestionName(selectedid, text);
        if (changed())
        {
            setChanged();
            notifyObservers();
        }
    }

    @Override
    public void nextQuestion() {
        state = state.nextQuestion();
        if (changed())
        {
            setChanged();
            notifyObservers();
        }
    }

    @Override
    public void playAgain() {
        state = state.playAgain();
        if (changed())
        {
            setChanged();
            notifyObservers();
        }
    }

    @Override
    public IQuestion getQuestionViewer() {
        return state.getQuestionViewer();
    }

    @Override
    public int getCorrectas() {
        return state.getCorrectas();
    }

    @Override
    public int getDifficulty() {
        return state.getDifficulty();
    }

    @Override
    public void saveQuizz(String string) {
        state = state.saveQuizz(string);
        if (changed())
        {
            setChanged();
            notifyObservers();
        }
    }

    @Override
    public void createQuizz() {
        state = state.createQuizz();
        if (changed())
        {
            setChanged();
            notifyObservers();
        }
    }

    @Override
    public IQuizz getQuizzInfo(int selectedIndex) {
        if (selectedIndex < 0 || selectedIndex >= quizzList.size())
            return null;
        
        String path;
        
        try {
            path = getQuizzesFolder() + File.separator + getQuizzFileName(selectedIndex);
        } catch (Exception ex) {
            Logger.getLogger(PrepareGame.class.getName()).log(Level.SEVERE, null, ex);
            return null;
        }
        
        File file = new File(path);
        
        try {
            ObjectInputStream ois = new ObjectInputStream(new FileInputStream(file));
            Quizz load = (Quizz) ois.readObject();                        
            setChanges();
            ois.close();
            return load;
        } catch (IOException ex) {
            Logger.getLogger(PrepareGame.class.getName()).log(Level.SEVERE, null, ex);
        } catch (ClassNotFoundException ex) {
            Logger.getLogger(PrepareGame.class.getName()).log(Level.SEVERE, null, ex);
        }
        return null;
    }

    @Override
    public void startGame(int selectedIndex, int d) {
        state = state.startGame(selectedIndex, d);
        if (changed()) 
        {
            setChanged();
            notifyObservers();
        }
    }

    @Override
    public void setAnswer(int i) {
        state = state.setAnswer(i);
        if (changed()) 
        {
            setChanged();
            notifyObservers();
        }
    }

    @Override
    public void loadQuizzData(int selectedIndex, String string) {
        state = state.loadQuizzData(selectedIndex, string);
        if (changed()) 
        {
            setChanged();
            notifyObservers();
        }
    }

    @Override
    public void editQuizz() {
        state = state.editQuizz();
        if (changed()) 
        {
            setChanged();
            notifyObservers();
        }
    } 
    
    
    
}
